/*
 * Copyright (C), 2002-2014, 你的兔宝宝电子商务有限公司
 * FileName: SNStringUtils.java
 * Author:   你的兔宝宝
 * Date:     2014-6-16 下午7:36:31
 * Description: 字符串工具类//模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.baby.demo.utils;

import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import freemarker.template.TemplateModelException;

/**
 * 字符串工具类<br>
 *
 * @author 你的兔宝宝
 */
public class Strings {

    private static final Logger LOGGER = LoggerFactory.getLogger(Strings.class);

    public static final String EMPTY = "";

    /**
     * 正则 匹配大括号{abc123}
     */
    public static final String FORMAT_RULE = "(\\{([a-zA-Z0-9_]{1,})([\\+\\-\\*]{1})?(\\d{1,})?\\})";

    /**
     * url正则
     */
    private static final Pattern URLRE = Pattern.compile("http://([^/:]+):?(\\d+)?(/(.*))*",
            Pattern.CASE_INSENSITIVE);
    
    /**
     * 数字正则
     */
    private static final String NUM_RE = "\\d+";
    
    private static final Pattern ERROR_MSG_RE = Pattern.compile(".*?Exception:(.*)", Pattern.CASE_INSENSITIVE);
    
    private static final String DATE_FORMAT = "yyyy-MM-dd";
    
    private Strings() {
    }
    
    /**
     * 
     * 功能描述: 判读是否为null<br>
     *
     * @param o
     * @return
     */
    public static boolean isNull(Object o) {
        return o == null;
    }
    
    public static boolean isNotNull(Object o) {
        return !isNull(o);
    }

    /**
     * 
     * 功能描述: 是否为空白字符串<br>
     * 〈功能详细描述〉
     *
     * @param o
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static boolean isEmpty(Object... os) {
        boolean empty = false;
        for( Object o : os ){
            empty = empty || ( isNull(o) || EMPTY.equals( o.toString().trim() ) );
        }
        return empty;
    }

    /**
     * 
     * 功能描述: 不为空<br>
     * 〈功能详细描述〉
     *
     * @param o
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static boolean isNotBlank(Object... os) {
        return !isEmpty(os);
    }

    /**
     * 
     * 功能描述: 如果指定对象为空则放回替代的字符串<br>
     * 〈功能详细描述〉
     *
     * @param o 需要判断字符串
     * @param ifEmpty 替代字符串
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String show(String o, String ifEmpty) {
        return isEmpty(o) ? show(ifEmpty) : show(o);
    }

    /**
     * 
     * 功能描述: 如果指定对象为空则放回替代的字符串<br>
     * 〈功能详细描述〉
     *
     * @param o 需要判断字符串
     * @param ifEmpty 替代字符串
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String show(Object o, Object ifEmpty) {
        return isEmpty(o) ? show(ifEmpty) : show(o);
    }

    /**
     * 
     * 功能描述: 如果指定字符串为null,则返回空字符串<br>
     *
     * @param os
     * @return
     */
    public static String show(String os) {
        return isEmpty(os) ? EMPTY : os;
    }

    /**
     * 
     * 功能描述: 如果指定对象为null,则返回空字符串<br>
     *
     * @param os
     * @return
     */
    public static String show(Object os) {
        return isEmpty(os) ? EMPTY : os.toString();
    }

    /**
     * 
     * 功能描述: 如果指定对象为空则放回替代的字符串<br>
     * 〈功能详细描述〉
     *
     * @param o 需要判断字符串
     * @param ifEmpty 替代字符串
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String show(Object o, String ifEmpty) {
        return isEmpty(o) ? show(ifEmpty) : show(o);
    }

    /**
     * 
     * 功能描述: 读取输入流为string<br>
     * 〈读取输入流为string〉
     *
     * @param is 输入流
     * @return
     * @throws IOException
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String show(InputStream is) {
        if (null == is) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        String line = null;
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8"));
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (Exception e) {
            LOGGER.error("show input stream error",e);
        } finally {
            Files.closeQuietly(is);
        }
        return sb.toString();
    }

    /**
     * 
     * 功能描述: 获取异常信息字符串<br>
     * 〈功能详细描述〉
     *
     * @param ex
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String exception(Exception ex) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        sw.append("[" + ex.getMessage() + "]");
        try {
            pw.close();
        } catch (Exception e) {
            LOGGER.warn("Transfer exception stack trace error!! Will return \"\"",e);
        }
        return sw.toString();
    }

    /**
     * 
     * 功能描述: 获取异常列表<br>
     * 〈功能详细描述〉
     *
     * @param ex
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static List<Throwable> exceptions(Exception ex) {
        List<Throwable> es = new ArrayList<Throwable>();
        Throwable t = ex;
        es.add(t);
        while ((t = t.getCause()) != null) {
            es.add(t);
        }
        return es;
    }

    /**
     * 
     * 功能描述: 友好展示错误信息<br>
     * 〈功能详细描述〉
     *
     * @param errorMsg
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String showMsg(String errorMsg) {
        return showMsg(ERROR_MSG_RE, errorMsg, "$1");
    }

    public static String showMsg(Pattern re, String pmsg) {
        return showMsg(re, pmsg, "$1");
    }

    public static String showMsg(String regexp, String pmsg) {
        return showMsg(regexp, pmsg, "$1");
    }

    public static String showMsg(String regexp, String pmsg, String omsg) {
        Pattern re = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
        return showMsg(re, pmsg, omsg);
    }

    public static String showMsg(Pattern re, String pmsg, String omsg) {
        String msg = pmsg;
        Matcher mMsg = re.matcher(msg);
        if (mMsg.matches()) {
            msg = mMsg.replaceAll(omsg);
        }
        return msg;
    }

    /**
     * 
     * 功能描述: 获取原始异常信息<br>
     * 〈功能详细描述〉
     *
     * @param t
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String showOriginalMsg(Throwable t) {
        Throwable t1 = t;
        while (t1.getCause() != null) {
            t1 = t1.getCause();
        }
        String errorMsg = t1.getMessage();
        return showMsg(errorMsg);
    }

    /**
     * 
     * 功能描述: 字符串截取<br>
     * 〈功能详细描述〉
     *
     * @param s
     * @param begin
     * @param end
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String substring(String s, int begin, int end) {
        try {
            return s.substring(begin, end);
        } catch (Exception e) {
            LOGGER.error("substring error",e);
        }
        return s;
    }

    /**
     * 替代三目运算符 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param yes
     * @param a
     * @param b
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String show(Object o, String a, String b) {
        return !isEmpty(o) ? a : b;
    }

    public static String show(String o, String a, String b) {
        return !isEmpty(o) ? a : b;
    }

    public static String show(boolean o, String a, String b) {
        return o ? a : b;
    }

    /**
     * 
     * 功能描述: 目标是否包含于数组中<br>
     * 〈功能详细描述〉
     *
     * @param target
     * @param arr
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static <T> boolean contiansIn(T target, T... arr) {
        boolean bcontain = false;
        for (T t : arr) {
            if (t != null && t.equals(target)) {
                bcontain = true;
                break;
            }
        }
        return bcontain;
    }

    /**
     * 
     * 功能描述: 获取布尔值<br>
     * 〈功能详细描述〉
     *
     * @param sl
     * @param ifNull
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static boolean getBoolean(String sl, boolean ifNull) {
        return getBoolean((Object) sl, ifNull);
    }

    public static boolean getBoolean(Object sl, boolean ifNull) {
        boolean ol = false;
        try {
            ol = Boolean.parseBoolean( show(sl) );
        } catch (Exception e) {
            ol = ifNull;
            LOGGER.warn("boolean error",e);
        }
        return ol;
    }
    
    public static boolean getBoolean(Map<String,Object> map,String propname,boolean ifNull){
        return getBoolean(get(map, propname),ifNull);
    }
    
    public static String format(Date date,String format){
        Date odate = date;
        if( odate == null ){
            odate = new Date();
        }
        String oformat = format;
        if( oformat == null){
            oformat = DATE_FORMAT;
        }
        return new SimpleDateFormat( format ).format( odate );
    }
    
    /**
     * 
     * 功能描述: 格式字符串中的内容<br>
     * 〈功能详细描述〉
     *
     * @example fromat("hello {name}",{name:'magic'})
     * @param config
     * @param rulename
     * @param paramsArr
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @SuppressWarnings("rawtypes")
    public static String format(Map<String,?> config,String rulename, Map... paramsArr){
        String rule = get(config, rulename);
        return format(rule,paramsArr);
    }
    
    public static String format(String rule, Object... objs) {
        Pattern p = Pattern.compile(FORMAT_RULE);
        Matcher m = p.matcher(rule);
        StringBuffer sb = new StringBuffer();
        try {
            boolean find = false;
            while (m.find()) {
                find = true;
                m.group();
                String prty = get(m.group(2), objs);
                String attr2 = m.group(4);
                if ( isNotBlank(attr2) ){
                    String prty2 = get(attr2, objs);
                    prty = EMPTY + oper(m.group(3), prty, prty2);
                }
                m.appendReplacement(sb, prty);// 用@@替换所有的55
            }
            if (find) {
                m.appendTail(sb);// 将最后一次替换后的字符串加上
            } else {
                return show(get(rule, objs), rule);
            }
        } catch (NullPointerException e) {
            LOGGER.warn("获取params属性出错！",e);
        } catch (Exception e) {
            LOGGER.warn("格式化字符串异常", e);
        }
        return sb.toString();
    }
    
    public static String format(Map<String,?> config,String rulename, String... objs){
        String rule = get(config, rulename);
        return format(rule,objs);
    }
    public static String format(String rule, String... objs) {
        Pattern p = Pattern.compile(FORMAT_RULE);
        Matcher m = p.matcher(rule);
        StringBuffer sb = new StringBuffer();
        try {
            boolean find = false;
            int i = 0;
            while (m.find()) {
                find = true;
                m.group();
                String prty = get(m.group(2),i++, objs);
                String attr2 = m.group(4);
                if ( isNotBlank(attr2) ){
                    String prty2 = get(attr2, objs);
                    prty = EMPTY + oper(m.group(3), prty, prty2);
                }
                m.appendReplacement(sb, prty);// 用@@替换所有的55
            }
            if (find) {
                m.appendTail(sb);// 将最后一次替换后的字符串加上
            } else {
                return show(get(rule, objs), rule);
            }
        } catch (NullPointerException e) {
            LOGGER.warn("获取params属性出错！",e);
        } catch (Exception e) {
            LOGGER.warn("格式化字符串异常", e);
        }
        return sb.toString();
    }

    @SuppressWarnings("rawtypes")
    public static String format(String rule, Map... paramsArr) {
        Pattern p = Pattern.compile(FORMAT_RULE);
        Matcher m = p.matcher(rule);
        StringBuffer sb = new StringBuffer();
        try {
            boolean find = false;
            while (m.find()) {
                find = true;
                m.group();
                String prty = get(m.group(2), paramsArr);
                String attr2 = m.group(4);
                if ( isNotBlank(attr2) ){
                    String prty2 = get(attr2, paramsArr);
                    prty = EMPTY + oper(m.group(3), prty, prty2);
                }
                m.appendReplacement(sb, prty);// 用@@替换所有的55
            }
            if (find) {
                m.appendTail(sb);// 将最后一次替换后的字符串加上
            } else {
                return show(get(rule, paramsArr), rule);
            }
        } catch (NullPointerException e) {
            LOGGER.warn("获取params属性出错！",e);
        } catch (Exception e) {
            LOGGER.warn("格式化字符串异常", e);
        }
        return sb.toString();
    }

    public static Matcher match(String rule, String target) {
        Pattern p = Pattern.compile(rule);
        return p.matcher(target);
    }

    /**
     * 
     * 功能描述: 简单四则运算<br>
     * 〈功能详细描述〉
     *
     * @param oper
     * @param op1
     * @param op2
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static int oper(String oper, String op1, String op2) {
        int result = 0;
        try {
            int ip1 = Integer.parseInt(op1),ip2 = Integer.parseInt(op2);
            if ("+".equals(oper)) {
                result = ip1 + ip2;
            } else if ("-".equals(oper)) {
                result = ip1 - ip2;
            } else if ("*".equals(oper)) {
                result = ip1 * ip2;
            } else if ("/".equals(oper)) {
                result = ip1 / ip2;
            } else if ("%".equals(oper)) {
                result = ip1 % ip2;
            }
        } catch (Exception e) {
            LOGGER.error(e.toString(),e);
        }
        return result;
    }

    /**
     * 
     * 功能描述: 如果指定字符串为不合法的整数，则返回替代的整数值<br>
     * 〈功能详细描述〉
     *
     * @param os
     * @param defaultInt
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static int getInt(String os, int defaultInt) {
        int intValue = defaultInt;
        try {
            if (!isEmpty(os) && Pattern.matches(NUM_RE, os) ) {
                intValue = Integer.parseInt(os);
            }
        } catch (Exception e) {
            LOGGER.warn("get int error-{}-{}",new Object[]{os,e.getMessage(),e});
        }
        return intValue;
    }

    public static int getInt(Object os, int defaultInt) {
        int intValue = defaultInt;
        try {
            if (!isEmpty(os)  && Pattern.matches(NUM_RE, show(os)) ) {
                intValue = Integer.parseInt(show(os));
            }
        } catch (Exception e) {
            LOGGER.warn("get int error-{}-{}",new Object[]{os,e.getMessage(),e});
        }
        return intValue;
    }

    public static int getInt(Map<String, Object> map, String pname, int defaultInt) {
        int intValue = defaultInt;
        try {
            String os = get(map, pname);
            if (!isEmpty(os)  && Pattern.matches(NUM_RE, os) ) {
                intValue = Integer.parseInt(show(os));
            }
        } catch (Exception e) {
            LOGGER.warn("get int error-{}-{}",new Object[]{pname,e.getMessage(),e});
        }
        return intValue;
    }

    /**
     * 从map中获取数据 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param map
     * @param name
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String get(Map<String, ? extends Object> map, String name) {
        return get(map, name, EMPTY);
    }

    public static String get(Map<String, ? extends Object> map, String name, String ifempty) {
        Object value = Collections.get(map, name);
        return show(value,ifempty);
    }

    /**
     * 
     * 功能描述: 从map数组中获取指定属性<br>
     * 〈功能详细描述〉
     *
     * @param name
     * @param maps
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static <T> String get(String name, Map... maps) {
        String s = EMPTY;
        for (Map map : maps) {
            if (isEmpty(s)) {
                s = get(map, name, EMPTY);
            } else {
                break;
            }
        }
        return s;
    }

    public static<T> String get(String name, T... objs) {
        String s = get(name,-1,objs);
        if( Strings.isEmpty(s) ){
            for (Object obj : objs) {
                if (isEmpty(s)) {
                    s = (String) get(obj, name);
                } else {
                    break;
                }
            }
        }
        return show(s);
    }
    
    public static<T> String get(String name,int at, T... objs) {
        T s = null;
        try{
            int oat = getInt(name, at);
            if( oat >= 0 && objs.length > oat ){
                s = objs[oat];
            }
        }catch (Exception e) {
            LOGGER.warn("格式化string...异常{}-{}",new Object[]{name,e.getMessage(),e});
        }
        return show(s);
    }
    
    public static String get(String name,int at, String... objs) {
        String s = EMPTY;
        try{
            int oat = getInt(name, at);
            if( oat >= 0 && objs.length > oat ){
                s = objs[oat];
            }
        }catch (Exception e) {
            LOGGER.warn("格式化string...异常{}-{}",new Object[]{name,e.getMessage(),e});
        }
        return show(s);
    }

    @SuppressWarnings("unchecked")
    public static Object get(Object obj, String name) {
        Object value = null;
        if (obj instanceof Map) {
            value = get((Map<String, Object>) obj, name);
        } else {
            try {
                PropertyDescriptor proDescriptor = new PropertyDescriptor(name, obj.getClass());
                Method methodGetUserName = proDescriptor.getReadMethod();
                value = methodGetUserName.invoke(obj);
            } catch (Exception e) {
                LOGGER.warn("get bean attr Error ", e);
            }
        }
        return value;
    }

    /**
     * 
     * 功能描述: 如果o为空选择t<br>
     * 〈功能详细描述〉
     *
     * @param o
     * @param t
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Object ifNull(Object o, Object t) {
        return o == null ? t : o;
    }

    /**
     * 
     * 功能描述：字符串特殊字符过滤 输入参数：<按照参数定义顺序>
     * 
     * @param 参数说明 返回值: 类型 <说明>
     * @return 返回值
     * @throw 异常描述
     * @see 需要参见的其它内容
     */
    public static String specCharHandle(String str) {
        String regEx = "[`~!@#$^&*()_\\-+=|{}':;',\\[\\]\\\\.<>?~！@#￥……&*（）——|{}【】‘；：”“\"'。，、？]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll(EMPTY).trim();
    }

    public static String join(Object... array) {
        return join(array, null);
    }

    public static String join(Object[] array, String separator) {
        if (array == null) {
            return null;
        }
        return join(array, separator, 0, array.length);
    }

    public static String join(Object[] array, String oseparator, int startIndex, int endIndex) {
        if (array == null) {
            return null;
        }
        String separator = oseparator;
        if (separator == null) {
            separator = EMPTY;
        }

        int bufSize = endIndex - startIndex;
        if (bufSize <= 0) {
            return EMPTY;
        }
        int ostart = 16;
        bufSize *= ((array[startIndex] == null ? ostart : array[startIndex].toString().length()) + separator
                .length());

        StringBuilder buf = new StringBuilder(bufSize);

        for (int i = startIndex; i < endIndex; i++) {
            if (i > startIndex) {
                buf.append(separator);
            }
            if (array[i] != null) {
                buf.append(array[i]);
            }
        }
        return buf.toString();
    }

    @SuppressWarnings("rawtypes")
    public static String join(Collection collection, String separator) {
        if (collection == null) {
            return null;
        }
        return join(collection.iterator(), separator);
    }

    @SuppressWarnings("rawtypes")
    public static String join(Iterator iterator, String separator) {

        // handle null, zero and one elements before building a buffer
        if (iterator == null) {
            return null;
        }
        if (!iterator.hasNext()) {
            return EMPTY;
        }
        Object first = iterator.next();
        if (!iterator.hasNext()) {
            return show(first);
        }

        // two or more elements
        int bufSize = 256;
        StringBuilder buf = new StringBuilder(bufSize);
        if (first != null) {
            buf.append(first);
        }

        while (iterator.hasNext()) {
            buf.append(separator);
            Object obj = iterator.next();
            if (obj != null) {
                buf.append(obj);
            }
        }

        return buf.toString();
    }

    /**
     * 
     * 功能描述: 获取url的uri<br>
     * 〈功能详细描述〉
     *
     * @param url
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String parseUri(String url) {
        String uri = EMPTY;
        Matcher mUrl = URLRE.matcher(url);
        if (mUrl.matches()) {
            mUrl.group();
            uri = mUrl.group(3);
        }
        return uri;
    }

    /**
     * 
     * 功能描述: iso转utf-8<br>
     * 〈功能详细描述〉
     *
     * @param s
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String iso2utf8(String s) {
        String os = EMPTY;
        try {
            byte[] bs = s.getBytes("ISO-8859-1");
            os = new String(bs, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            LOGGER.error(e.toString(),e);
        }
        return os;
    }

    /**
     * 获取ftl错误堆栈 功能描述: <br>
     * 〈功能详细描述〉
     *
     * @param ex
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String showFtlStack(Exception ex) {
        if (ex instanceof TemplateModelException) {
            TemplateModelException e = (TemplateModelException) ex;
            return e.getFTLInstructionStack();
        }
        return null;
    }

    public static String uuid() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replace("-", "");
    }
    
    public static String text(String html){
        html = html.replace("&", "&#38;");
        html = html.replace("'", "&#39;");
        return html;
    }
    
    public static String bversion(){
        return format(new Date(), "yyyyMMddhhmmss");
    }
    
    public static String parseNum(String os){
        String reg = "(\\.*0+)?([Ee]\\d+0*)?$";
        return show(os).replaceAll(reg, "");
    }
    
    /**
     * 
     * 功能描述: 文本行查找<br>
     * 〈功能详细描述〉
     *
     * @param stream
     * @param regex
     * @param replacement
     * @return
     * @Author:   你的兔宝宝
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String searchOne(String stream,String regex,String replacement){
        Scanner scanner = new Scanner(stream);
        String target = null;
        Pattern p = Pattern.compile(regex);
        while(scanner.hasNext()){
            String line = scanner.nextLine();
            Matcher m = p.matcher(line);
            if(m.find()){
                target = line;
                if( replacement != null ){
                    target = line.replaceAll(regex, replacement);
                }
                break;
            }
        }
        return target;
    }
    
    public static String[] search(String stream,String regex,String replacement){
        Scanner scanner = new Scanner(stream);
        List<String> target = new ArrayList<String>();
        Pattern p = Pattern.compile(regex);
        while(scanner.hasNext()){
            String line = scanner.nextLine();
            Matcher m = p.matcher(line);
            if(m.find()){
                if( replacement != null ){
                    target.add(line.replaceAll(regex, replacement));
                }else{
                    target.add(line);
                }
            }
        }
        String[] lines = new String[target.size()];
        return target.toArray(lines);
    }
    
    public static class LineCallback{
        public String replace(String line,String target){return line;};
        public String replace(String line,String target,int regexat){return line;};
    }
    
    /**
     * 
     * 功能描述: 文本替换<br>
     * 〈功能详细描述〉
     *
     * @param stream
     * @param regex
     * @param groupname
     * @param cb
     * @return
     * @Author:   你的兔宝宝
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static String replaceTxt(String stream,String regex,String groupname,LineCallback cb){
        Scanner scanner = new Scanner(stream);
        List<String> lines = new ArrayList<String>();
        Pattern p = Pattern.compile(regex);
        while(scanner.hasNext()){
            String line = scanner.nextLine();
            Matcher m = p.matcher(line);
            while(m.find()){
                String target = m.group(groupname);
                line = cb.replace(line,target);
            }
            lines.add(line);
        }
        return join(lines,"\n");
    }
    
    public static String replaceTxt(String stream,String[] regexs,String groupname,LineCallback cb,boolean norepeat){
        Scanner scanner = new Scanner(stream);
        List<String> lines = new ArrayList<String>();
        Pattern[] ps = new Pattern[regexs.length];
        int i = 0;
        for(String regex:regexs){
            ps[i++] = Pattern.compile(regex);
        }
        while(scanner.hasNext()){
            String line = scanner.nextLine();
            i = 0;
            for(Pattern p:ps){
                Matcher m = p.matcher(line);
                boolean matched = false;
                while(m.find()){
                    String target = m.group(groupname);
                    line = cb.replace(line,target,i);
                    matched = true;
                }
                if(matched&&norepeat){
                    break;
                }
                i++;
            }
            lines.add(line);
        }
        return join(lines,"\n");
    }
    
    public static String replaceTxt(String stream,String[] regexs,String groupname,LineCallback cb){
        return replaceTxt(stream,regexs,groupname,cb,true);
    }
}
